using BackData;
using Domain.工艺工序;
using Infratructure;
using MediatR;
using Microsoft.Extensions.Logging;
using Team.API.Applocation.Command.Makesteps;
using System.Transactions;
using Yitter.IdGenerator;
using Domain;

namespace Team.API.Applocation.Hanldler.Makesteps
{
    /// <summary>
    /// 批量保存工艺流程处理器
    /// 清除旧的工艺流程（根据产品名称和版本），保存新的工艺流程列表
    /// </summary>
    public class SaveMakestepListHandler : IRequestHandler<SaveMakestepListCommand, APIResult<bool>>
    {
        private readonly IRepository<Makestepmodel> repository;
        private readonly IRepository<Nlogmodel> logRepository;
        private readonly ILogger<SaveMakestepListHandler> logger;

        public SaveMakestepListHandler(
            IRepository<Makestepmodel> repository,
            IRepository<Nlogmodel> logRepository,
            ILogger<SaveMakestepListHandler> logger)
        {
            this.repository = repository;
            this.logRepository = logRepository;
            this.logger = logger;
        }

        /// <summary>
        /// 批量保存工艺流程
        /// 1. 软删除旧的工艺流程（根据产品名称和版本，Parentid=0）
        /// 2. 创建新的工艺流程记录
        /// 3. 记录操作日志
        /// </summary>
        /// <param name="request">保存命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>保存结果</returns>
        public async Task<APIResult<bool>> Handle(SaveMakestepListCommand request, CancellationToken cancellationToken)
        {
            try
            {
                // 验证必填参数
                if (string.IsNullOrWhiteSpace(request.Goodsname))
                {
                    return APIResult<bool>.Faile("产品名称不能为空");
                }

                if (string.IsNullOrWhiteSpace(request.Version))
                {
                    return APIResult<bool>.Faile("版本号不能为空");
                }

                if (request.ProcessSteps == null || request.ProcessSteps.Count == 0)
                {
                    return APIResult<bool>.Faile("工艺流程列表不能为空");
                }

                // 获取当前操作人
                var currentUser = request.CurrentUserName ?? "系统";

                // 使用事务确保数据一致性
                using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        // 1. 软删除旧的工艺流程（根据产品名称和版本，Parentid=0，只删除根节点）
                        var oldProcessSteps = await repository.GetAll()
                            .Where(x => !x.IsDel
                                && x.Parentid == 0
                                && x.Goodsname == request.Goodsname
                                && x.Version == request.Version)
                            .ToListAsync();

                        if (oldProcessSteps != null && oldProcessSteps.Count > 0)
                        {
                            // 同时删除所有子节点（根据父级ID）
                            var oldIds = oldProcessSteps.Select(x => x.Id).ToList();
                            
                            // 递归查找所有子节点并删除
                            var allOldIds = new List<long>(oldIds);
                            foreach (var id in oldIds)
                            {
                                var children = await GetChildrenIdsAsync(id);
                                allOldIds.AddRange(children);
                            }

                            // 软删除所有节点
                            foreach (var id in allOldIds.Distinct())
                            {
                                var entity = await repository.GetByIdAsync(id);
                                if (entity != null)
                                {
                                    entity.IsDel = true;
                                    await repository.UpdateAsync(entity);
                                }
                            }

                            logger.LogInformation("[工艺流程-批量保存] 已删除旧的工艺流程，产品名称={Goodsname}，版本={Version}，共{Count}条",
                                request.Goodsname, request.Version, allOldIds.Count);
                        }

                        // 2. 创建新的工艺流程记录（按排序顺序）
                        var sortedSteps = request.ProcessSteps.OrderBy(x => x.SortOrder).ToList();
                        var newIds = new List<long>();

                        foreach (var stepDto in sortedSteps)
                        {
                            var entity = new Makestepmodel
                            {
                                Id = YitIdHelper.NextId(),
                                Processname = stepDto.Processname,
                                Processcode = stepDto.Processcode,
                                Processdescription = stepDto.Processdescription ?? "",
                                Version = stepDto.Version,
                                Goodsname = stepDto.Goodsname,
                                Deliverables = stepDto.Deliverables ?? "",
                                Kahuna = stepDto.Kahuna ?? "",
                                Departmentname = stepDto.Departmentname ?? "",
                                IsUse = stepDto.IsUse,
                                SpanTime = stepDto.SpanTime,
                                EquipmentId = stepDto.EquipmentId,
                                Parentid = stepDto.Parentid, // 扁平列表，所有工序的父级ID为0
                                IsDel = false
                            };

                            // 将备注信息保存到描述字段（如果描述为空）
                            if (string.IsNullOrWhiteSpace(entity.Processdescription) && !string.IsNullOrWhiteSpace(stepDto.Remark))
                            {
                                entity.Processdescription = stepDto.Remark;
                            }

                            var effect = await repository.AddAsync(entity);
                            if (effect <= 0)
                            {
                                throw new Exception($"保存工序失败：{entity.Processname}");
                            }
                            newIds.Add(entity.Id);
                        }

                        // 3. 记录操作日志
                        try
                        {
                            var logEntity = new Nlogmodel
                            {
                                Id = YitIdHelper.NextId(),
                                Operatingtime = DateTime.Now,
                                Operator = currentUser,
                                Message = $"{currentUser}批量保存工艺流程：{request.Goodsname}（{request.Version}），共{newIds.Count}条工序",
                                Category = "Process",
                                Otherkey = newIds.Count > 0 ? newIds[0] : 0, // 使用第一条工序的ID作为外键
                                IsDel = false
                            };
                            var logEffect = await logRepository.AddAsync(logEntity);
                            if (logEffect <= 0)
                            {
                                logger.LogWarning("[工艺流程-批量保存] 日志写入失败，操作人：{User}，产品名称：{Goodsname}",
                                    currentUser, request.Goodsname);
                            }
                        }
                        catch (Exception logEx)
                        {
                            logger.LogWarning(logEx, "[工艺流程-批量保存] 日志写入异常，操作人：{User}，产品名称：{Goodsname}",
                                currentUser, request.Goodsname);
                        }

                        // 提交事务
                        transaction.Complete();

                        logger.LogInformation("[工艺流程-批量保存] 保存成功，操作人：{User}，产品名称={Goodsname}，版本={Version}，共{Count}条",
                            currentUser, request.Goodsname, request.Version, newIds.Count);

                        return APIResult<bool>.Ok("工艺流程保存成功", true);
                    }
                    catch (Exception ex)
                    {
                        logger.LogError(ex, "[工艺流程-批量保存] 保存失败，操作人：{User}，产品名称：{Goodsname}",
                            currentUser, request.Goodsname);
                        return APIResult<bool>.Faile($"工艺流程保存失败：{ex.Message}");
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "[工艺流程-批量保存] 执行异常，产品名称：{Goodsname}，版本：{Version}",
                    request.Goodsname, request.Version);
                return APIResult<bool>.Faile($"工艺流程保存失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 递归获取所有子节点的ID
        /// </summary>
        /// <param name="parentId">父级ID</param>
        /// <returns>子节点ID列表</returns>
        private async Task<List<long>> GetChildrenIdsAsync(long parentId)
        {
            var children = await repository.GetAll()
                .Where(x => !x.IsDel && x.Parentid == parentId)
                .ToListAsync();

            var result = new List<long>();
            if (children != null && children.Count > 0)
            {
                result.AddRange(children.Select(x => x.Id));
                foreach (var child in children)
                {
                    var grandchildren = await GetChildrenIdsAsync(child.Id);
                    result.AddRange(grandchildren);
                }
            }

            return result;
        }
    }
}

